/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "web_download_delegate.h"

#include <cstring>

#include "ani_business_error.h"
#include "ani_parse_utils.h"
#include "web_errors.h"
#include "nweb_c_api.h"
#include "nweb_log.h"
#include "web_download_manager.h"

namespace OHOS {
namespace NWeb {
namespace {
const char* WEB_DOWNLOAD_ITEM_CLASS_NAME = "L@ohos/web/webview/webview/WebDownloadItem;";
}

WebDownloadDelegate::WebDownloadDelegate(ani_env* env)
    : delegate_(nullptr),
      download_before_start_callback_(nullptr),
      env_(env)
{
    WVLOG_D("WebDownloadDelegate::WebDownloadDelegate");
}

WebDownloadDelegate::~WebDownloadDelegate()
{
    WVLOG_D("[DOWNLOAD] WebDownloadDelegate::~WebDownloadDelegate");
    if (download_before_start_callback_) {
        env_->GlobalReference_Delete(download_before_start_callback_);
    }
    WebDownloadManager::RemoveDownloadDelegate(this);
}

void WebDownloadDelegate::RemoveSelfRef()
{
    if (delegate_) {
        env_->GlobalReference_Delete(delegate_);
        delegate_ = nullptr;
    }
}

void WebDownloadDelegate::DownloadBeforeStart(WebDownloadItem *webDownloadItem)
{
    WVLOG_D("[DOWNLOAD] WebDownloadDelegate::DownloadBeforeStart");
    if (env_ == nullptr) {
        WVLOG_E("[DOWNLOAD] WebDownloadDelegate::DownloadBeforeStart nil env");
        return;
    }

    if (!download_before_start_callback_ || !webDownloadItem) {
        WVLOG_E("[DOWNLOAD] download_before_start_callback_ or webDownloadItem is null.");
        return;
    }

    ani_class cls;
    ani_status status;
    if ((status = env_->FindClass(WEB_DOWNLOAD_ITEM_CLASS_NAME, &cls)) != ANI_OK) {
        WVLOG_E("[DOWNLOAD] FindClass status: %{public}d", status);
        return;
    }
    ani_method ctor;
    if ((status = env_->Class_FindMethod(cls, "<ctor>", "Lstd/core/String;:V", &ctor)) != ANI_OK) {
        WVLOG_E("[DOWNLOAD] Class_FindMethod status: %{public}d", status);
        return;
    }
    ani_string result_string{};
    if ((status = env_->String_NewUTF8(webDownloadItem->url.c_str(), webDownloadItem->url.size(), &result_string)) !=
        ANI_OK) {
        WVLOG_E("[DOWNLOAD] String_NewUTF8 status: %{public}d", status);
        return;
    }
    ani_object inputObject = nullptr;
    if ((status = env_->Object_New(cls, ctor, &inputObject, result_string)) != ANI_OK) {
        WVLOG_E("[DOWNLOAD] Object_New status: %{public}d", status);
        return;
    }
    if (inputObject == nullptr) {
        WVLOG_E("[DOWNLOAD] inputObject is null");
        return;
    }

    std::vector<ani_ref> vec;
    vec.push_back(static_cast<ani_object>(inputObject));
    ani_ref fnReturnVal;
    env_->FunctionalObject_Call(reinterpret_cast<ani_fn_object>(download_before_start_callback_),
                                vec.size(), vec.data(), &fnReturnVal);
}

void WebDownloadDelegate::PutDownloadBeforeStart(ani_fn_object callback)
{
    WVLOG_I("[DOWNLOAD] WebDownloadDelegate::PutDownloadBeforeStart");
    env_->GlobalReference_Create(reinterpret_cast<ani_ref>(callback), &download_before_start_callback_);
}

int32_t WebDownloadDelegate::GetNWebId() const
{
    return nwebId_;
}

void WebDownloadDelegate::SetNWebId(int32_t nwebId)
{
    nwebId_ = nwebId;
}

ani_env* WebDownloadDelegate::GetEnv()
{
    return env_;
}
} // namespace NWeb
} // namespace OHOS
